home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  12.5 KB  |  446 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 32
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /************************************************************************
  4.  * functions for dealing with printing
  5.  ************************************************************************/
  6. #pragma load EUDORA_LOAD
  7. #pragma segment Print
  8.  
  9. /************************************************************************
  10.  * private function declarations
  11.  ************************************************************************/
  12.     int PrintMessage(MyWindowPtr win,Boolean isOut, Rect *uRect, Boolean select);
  13.     void PrintMessageHeader(UPtr title, short pageNum, short height, short bottom, short left, short right);
  14.     int PrintMessagePage(UPtr title, UHandle text,long size,long *offset,Rect *uRect,short hMar,short pageNum);
  15.     int PrintCompMessage(UPtr title, MessType **messH,Rect *uRect,short hMar);
  16.     void CollectReturnAddr(UPtr returnAddr);
  17.     void SetupPrintFont(void);
  18.     void GetURect(Rect *useRect);
  19. /************************************************************************
  20.  * PrintSelectedMessages - print out a given message.  Handles the print
  21.  * manager stuff.
  22.  ************************************************************************/
  23. int PrintSelectedMessages(TOCType **tocH,Boolean select)
  24. {
  25.     int err, cumErr=0;
  26.     TPPrPort port;
  27.     GrafPtr oldPort;
  28.     TPrStatus status;
  29.     int sumNum;
  30.     MessType **messH;
  31.     Boolean isOut;
  32.     Str31 outName;
  33.     Rect uRect;
  34.     
  35.     select = select || 0!=(CurrentModifiers()&shiftKey);
  36.     
  37.     GetPort(&oldPort);
  38.     PrOpen();
  39.     if (PrError())
  40.     {
  41.         WarnUser(NO_PRINTER,PrError());
  42.         return(PrError());
  43.     }
  44.     
  45.     if (PageSetup==nil) PageSetup = GetResource(PRINT_RTYPE,PRINT_CSOp);
  46.     if (PageSetup==nil)
  47.     {
  48.         PageSetup = NuHandle(sizeof(TPrint));
  49.         if (PageSetup==nil) {WarnUser(COULDNT_SETUP,err=MemError()); goto done;}
  50.         PrintDefault(PageSetup);
  51.     }
  52.     else
  53.         PrValidate(PageSetup);
  54.     
  55.     PushCursor(arrowCursor);
  56.     if (PrJobDialog(PageSetup))
  57.     {
  58.         PopCursor();
  59.         port = PrOpenDoc(PageSetup,nil,nil);
  60.         if (!port) {WarnUser(NO_PPORT,err=MemError()); goto done;}
  61.         GetURect(&uRect);
  62.         isOut = EqualString(GetRString(outName,OUT),LDRef(tocH)->name,False,True);
  63.         UL(tocH);
  64.         for (sumNum=0;sumNum<(*tocH)->count;sumNum++)
  65.             if ((*tocH)->sums[sumNum].selected)
  66.             {
  67.                 messH = (*tocH)->sums[sumNum].messH;
  68.                 if (messH || !(err=!GetAMessage(tocH,sumNum,nil,False)))
  69.                 {
  70.                     SetPort(port);
  71.                     err = PrintMessage((*(MessHandle)(*tocH)->sums[sumNum].messH)->win,isOut,&uRect,select);
  72.                     if (!messH)
  73.                         CloseMyWindow((*(MessType **)(*tocH)->sums[sumNum].messH)->win);
  74.                     if (err) cumErr = err;
  75.                 }
  76.             }
  77.         PrCloseDoc(port);
  78.         if ((*PageSetup)->prJob.bJDocLoop==bSpoolLoop && !err && !PrError())
  79.             PrPicFile(PageSetup,nil,nil,nil,&status);
  80.         if (cumErr) WarnUser(PART_PRINT_FAIL,err);
  81.     }
  82.     else
  83.         PopCursor();
  84. done:
  85.     PrClose();
  86.     FigureOutFont();
  87.     SetPort(oldPort);
  88.     return(err);
  89. }
  90.  
  91. /************************************************************************
  92.  * PrintOneMessage - print out a given message.  Handles the print manager
  93.  * stuff.
  94.  ************************************************************************/
  95. int PrintOneMessage(MyWindowPtr win,Boolean select)
  96. {
  97.     int err;
  98.     TPPrPort port;
  99.     GrafPtr oldPort;
  100.     TPrStatus status;
  101.     Rect uRect;
  102.     Boolean isOut;
  103.     
  104.     select = select || 0!=(CurrentModifiers()&shiftKey);
  105.     
  106.     GetPort(&oldPort);
  107.     PrOpen();
  108.     if (PrError())
  109.     {
  110.         WarnUser(NO_PRINTER,PrError());
  111.         return(PrError());
  112.     }
  113.     
  114.     if (PageSetup==nil) PageSetup = GetResource(PRINT_RTYPE,PRINT_CSOp);
  115.     if (PageSetup==nil)
  116.     {
  117.         PageSetup = NuHandle(sizeof(TPrint));
  118.         if (PageSetup==nil) {WarnUser(COULDNT_SETUP,err=MemError()); goto done;}
  119.         PrintDefault(PageSetup);
  120.     }
  121.     else
  122.         PrValidate(PageSetup);
  123.     
  124.     PushCursor(arrowCursor);    
  125.     if (PrJobDialog(PageSetup))
  126.     {
  127.         PopCursor();
  128.         port = PrOpenDoc(PageSetup,nil,nil);
  129.         GetURect(&uRect);
  130.         if (!port) {WarnUser(NO_PPORT,err=MemError()); goto done;}
  131.         isOut = win->qWindow.windowKind==COMP_WIN;
  132.         SetPort(port);
  133.         err = PrintMessage(win,isOut,&uRect,select);
  134.         PrCloseDoc(port);
  135.         if ((*PageSetup)->prJob.bJDocLoop==bSpoolLoop && !err && !PrError())
  136.             PrPicFile(PageSetup,nil,nil,nil,&status);
  137.         if (err) WarnUser(PRINT_FAILED,err);
  138.     }
  139.     else
  140.         PopCursor();
  141. done:
  142.     PrClose();
  143.     FigureOutFont();
  144.     SetPort(oldPort);
  145.     return(err);
  146. }
  147.  
  148. /************************************************************************
  149.  * PrintMessage - print a given message, assuming everything is already
  150.  * set up with the print manager.
  151.  ************************************************************************/
  152. int PrintMessage(MyWindowPtr win,Boolean isOut, Rect *uRect,Boolean select)
  153. {
  154.     long offset = 0;
  155.     short hMar = GetRLong(PRINT_H_MAR);
  156.     int err;
  157.     short pageNum=0;
  158.     Str255 title;
  159.     GrafPtr port;
  160.     short device = ((*PageSetup)->prStl.wDev>>8)&0xff;
  161.     Boolean isMessage;
  162.     TEHandle teh;
  163.     
  164.     isMessage = win->qWindow.windowKind==COMP_WIN ||
  165.                             win->qWindow.windowKind==MESS_WIN;
  166.     teh = isMessage ? Win2Body(win) : WinTEH(win);
  167.     
  168. #define bDevLaser 3
  169.     
  170.     GetPort(&port);
  171.     
  172.     SetupPrintFont();
  173.     TextFont(FontID);
  174.     TextSize(FontSize);
  175.     PCopy(title,*win->qWindow.titleHandle);
  176.     if (!isOut)
  177.     {
  178.         long size = (*teh)->teLength;
  179.         if (select && (*teh)->selStart<(*teh)->selEnd)    /* print selection */
  180.         {
  181.             offset = (*teh)->selStart;
  182.             size = (*teh)->selEnd;
  183.         }
  184.         do
  185.         {
  186.             GiveTime();
  187.             err=PrintMessagePage(title,(*teh)->hText,size,
  188.                                                                                              &offset,uRect,hMar,++pageNum);
  189.         }
  190.         while (!err && offset < size);
  191.     }
  192.     else
  193.         err = PrintCompMessage(title,(MessHandle)win->qWindow.refCon,uRect,hMar);
  194.     if (!err && isMessage && SumOf(Win2MessH(win))->state == UNREAD)
  195.         SetState((*Win2MessH(win))->tocH,(*Win2MessH(win))->sumNum,READ);
  196.     return(err);
  197. }
  198.  
  199. /************************************************************************
  200.  * PrintMessagePage - print a pageful of the current message
  201.  ************************************************************************/
  202. int PrintMessagePage(UPtr title, UHandle text,long size,long *offset,Rect *uRect,short hMar,short pageNum)
  203. {
  204.     short baseV=uRect->top+hMar+FontLead;
  205.     short lastBase = uRect->bottom-hMar-FontDescent;
  206.     Str255 returnAddr;
  207.     UPtr begin,spot,end,wrap,space;
  208.     short width=uRect->right-uRect->left;
  209.     
  210.     CollectReturnAddr(returnAddr);
  211.     PrOpenPage(qd.thePort,nil);
  212.     PrintMessageHeader(title,pageNum,hMar,
  213.                                                                 uRect->top+hMar,uRect->left,uRect->right);
  214.     begin = LDRef(text) + *offset;
  215.     end = *text + size;
  216.     for (; begin<end && baseV<lastBase; baseV+=FontLead,begin=spot)
  217.     {
  218.         /*
  219.          * point end at the end of the current line
  220.          */
  221.         for (spot=begin;spot<end;spot++) if (*spot=='\n') break;
  222.         wrap = begin + CalcTextTrunc(begin,spot-begin,width,qd.thePort);
  223.         if (wrap>end) wrap = end;
  224.         space = nil;
  225.         for (spot=begin; spot<wrap; spot++) if (*spot==' ') space=spot;
  226.         if (*spot!='\n')
  227.         {
  228.             if (spot!=end)
  229.                 spot = space ? space : spot+1;
  230.         }
  231.         
  232.         if (spot>begin)
  233.         {
  234.             MoveTo(uRect->left,baseV);
  235.             DrawText(begin,0,spot-begin);
  236.         } 
  237.  
  238.         if (*spot=='\n')
  239.             spot++; /* skip newline */
  240.         else
  241.             while (spot<end && *spot==' ') spot++; /* skip trailing blanks */
  242.     }
  243.     *offset = spot-*text;
  244.     HUnlock(text);
  245.     PrintMessageHeader(returnAddr,pageNum,hMar,
  246.                                                                 uRect->bottom,uRect->left,uRect->right);
  247.     PrClosePage(qd.thePort);
  248.     return(PrError());
  249. }
  250.  
  251. /************************************************************************
  252.  * PrintCompMessage - print a composition message
  253.  * this is an ugly hack--so shoot me.
  254.  ************************************************************************/
  255. int PrintCompMessage(UPtr title, MessType **messH,Rect *uRect,short hMar)
  256. {
  257.     short baseV;
  258.     short lastBase = uRect->bottom-hMar-FontDescent;
  259.     int err;
  260.     int pageNum=1;
  261.     Str31 headerName;
  262.     Str255 returnAddr;
  263.     int hOffset;
  264.     UPtr begin=nil,spot,end,wrap,space;
  265.     int tx=0;
  266.     
  267.     CollectReturnAddr(returnAddr);
  268.     GetRString(headerName,HEADER_STRN+ATTACH_HEAD);
  269.     hOffset = StringWidth(headerName) + FontWidth;
  270.     baseV=uRect->top+hMar+FontLead;
  271.     PrOpenPage(qd.thePort,nil);
  272.     PrintMessageHeader(title,pageNum,hMar,
  273.                                                                 uRect->top+hMar,uRect->left,uRect->right);
  274.     do
  275.     {
  276.         if (!begin)
  277.         {
  278.             begin = LDRef((*(*messH)->txes[tx])->hText);
  279.             end = begin + (*(*messH)->txes[tx])->teLength;
  280.             if (tx==HEAD_LIMIT-1)
  281.             {
  282.                 baseV += FontLead;
  283.                 hOffset = 0;
  284.                 *headerName = 0;
  285.             }
  286.             else
  287.                 GetRString(headerName,HEADER_STRN+tx+1);
  288.         }
  289.         else
  290.         {
  291.             baseV=uRect->top+hMar+FontLead;
  292.             PrOpenPage(qd.thePort,nil);
  293.             PrintMessageHeader(title,pageNum,hMar,
  294.                                                                         uRect->top+hMar,uRect->left,uRect->right);
  295.         }
  296.         for (; begin<end && baseV<lastBase; baseV+=FontLead,begin=spot)
  297.         {
  298.             /*
  299.                 * point end at the end of the current line
  300.                 */
  301.             for (spot=begin;spot<end;spot++) if (*spot=='\n') break;
  302.             wrap = begin + CalcTextTrunc(begin,spot-begin,
  303.                                              uRect->right-uRect->left-hOffset,qd.thePort);
  304.             if (wrap>end) wrap = end;
  305.             space = nil;
  306.             for (spot=begin; spot<wrap; spot++) if (*spot==' ') space=spot;
  307.             if (*spot!='\n')
  308.             {
  309.                 if (spot!=end)
  310.                     spot = space ? space : spot+1;
  311.             }
  312.             
  313.             if (spot>begin)
  314.             {
  315.                 if (*headerName)
  316.                 {
  317.                     MoveTo(uRect->left+hOffset-StringWidth(headerName)-FontWidth,baseV);
  318.                     DrawString(headerName);
  319.                     DrawChar(' ');
  320.                     *headerName=0;
  321.                 }
  322.                 MoveTo(uRect->left+hOffset,baseV);
  323.                 DrawText(begin,0,spot-begin);
  324.             } 
  325.     
  326.             if (*spot=='\n')
  327.                 spot++; /* skip newline */
  328.             else
  329.                 while (spot<end && *spot==' ') spot++; /* skip trailing blanks */
  330.         }
  331.         if (begin>=end)
  332.         {
  333.             HUnlock((*(*messH)->txes[tx])->hText);
  334.             tx++;
  335.             begin=nil;
  336.         }
  337.         else
  338.         {
  339.             PrintMessageHeader(returnAddr,pageNum++,hMar,
  340.                                                                         uRect->bottom,uRect->left,uRect->right);
  341.             PrClosePage(qd.thePort);
  342.         }
  343.     }
  344.     while (!(err=PrError()) && tx<HEAD_LIMIT);
  345.     PrintMessageHeader(returnAddr,pageNum,hMar,
  346.                                                                 uRect->bottom,uRect->left,uRect->right);
  347.     PrClosePage(qd.thePort);
  348.     return(PrError());
  349. }
  350.  
  351. /************************************************************************
  352.  * PrintMessageHeader - print a header with the message info in it.
  353.  ************************************************************************/
  354. void PrintMessageHeader(UPtr title, short pageNum, short height, short bottom, short left, short right)
  355. {
  356.     Rect border;
  357.     short h,v;
  358.     Str31 pageStr;
  359.     short pageStrWidth;
  360.     GrafPtr port;
  361.     short oldFontId;
  362.     
  363.     SetRect(&border,left,bottom-height,right,bottom);
  364.     FillRect(&border,&qd.gray);
  365.     InsetRect(&border,1,1);
  366.     EraseRect(&border);
  367.     GetPort(&port);
  368.     oldFontId = port->txFont;
  369.     
  370.     v = bottom - height/4;
  371.     TextFace(bold);
  372.     TextSize(GetRLong(PRINT_H_SIZE));
  373.     TextFont(GetFontID(GetRString(pageStr,PRINT_H_FONT)));
  374.     NumToString(pageNum,pageStr);
  375.     pageStrWidth = StringWidth(pageStr);
  376.     h = right - height - pageStrWidth;
  377.     MoveTo(h,v);
  378.     DrawString(pageStr);
  379.     h = left + height;
  380.     MoveTo(h,v);
  381.     DrawText(title,1,CalcTrunc(title,right-3*height-pageStrWidth-left,port));
  382.     
  383.     TextFont(oldFontId);
  384.     TextFace(0);
  385.     TextSize(FontSize);
  386. }
  387.  
  388. /************************************************************************
  389.  * CollectReturnAddr - collect the return addr for the bottoms of printouts
  390.  ************************************************************************/
  391. void CollectReturnAddr(UPtr returnAddr)
  392. {
  393.     short len;
  394.     char saveChar;
  395.     
  396.     GetRString(returnAddr,RETURN_PRINT_INTRO);
  397.     len = *returnAddr;
  398.     saveChar = returnAddr[len];
  399.     GetReturnAddr(returnAddr+len,True);
  400.     *returnAddr += returnAddr[len];
  401.     returnAddr[len] = saveChar;
  402. }
  403.  
  404. /************************************************************************
  405.  * SetupPrintFont - set up the font to use for printing
  406.  ************************************************************************/
  407. void SetupPrintFont(void)
  408. {
  409.     Str31 scratch;
  410.     short fID,fSize;
  411.     short device = ((*PageSetup)->prStl.wDev>>8)&0xff;
  412.     
  413.     GetPref(scratch,PREF_PRINT_FONT);
  414.     fID = *scratch ? GetFontID(GetPref(scratch,PREF_PRINT_FONT))
  415.                                  : FontIsFixed ?
  416.                                      GetFontID(GetRString(scratch,PRINT_FONT)) : FontID;
  417.     GetPref(scratch,PREF_PRINT_FONT_SIZE);
  418.     fSize = *scratch ? GetRLong(PREF_STRN+PREF_PRINT_FONT_SIZE) : FontSize;
  419.     if (fSize!=FontSize || fID!=FontID)
  420.     {
  421.         FontID = fID;
  422.         FontSize = fSize;
  423.         FontWidth = GetWidth(FontID,FontSize);
  424.         FontLead = GetLeading(FontID,FontSize);
  425.         FontDescent = GetDescent(FontID,FontSize);
  426.         FontAscent = GetAscent(FontID,FontSize);
  427.         FontIsFixed = IsFixed(FontID,FontSize);
  428.     }
  429. }
  430.  
  431. /************************************************************************
  432.  *
  433.  ************************************************************************/
  434. void GetURect(Rect *useRect)
  435. {
  436.     short t;
  437.     Rect uRect;
  438.     uRect = (*PageSetup)->prInfo.rPage;
  439.     InsetRect(&uRect,3,3);    /* Apple lies about page size sometimes */
  440.     t = (*PageSetup)->rPaper.left+GetRLong(PRINT_LEFT_MAR);
  441.     uRect.left = MAX(uRect.left,t);
  442.     t = (*PageSetup)->rPaper.right-GetRLong(PRINT_RIGHT_MAR);
  443.     uRect.right = MIN(uRect.right,t);
  444.     *useRect = uRect;
  445. }
  446.